package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.UserLoginRequestDto;
import com.zzyl.entity.Contract;
import com.zzyl.entity.Elder;
import com.zzyl.entity.Member;
import com.zzyl.entity.Order;
import com.zzyl.exception.BusinessException;
import com.zzyl.mapper.ContractMapper;
import com.zzyl.mapper.ElderMapper;
import com.zzyl.mapper.MemberMapper;
import com.zzyl.mapper.OrderMapper;
import com.zzyl.properties.JwtProperties;
import com.zzyl.properties.WechatConfigProperties;
import com.zzyl.service.MemberService;
import com.zzyl.utils.JwtUtil;
import com.zzyl.vo.LoginVo;
import com.zzyl.vo.MemberVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {
    // 默认账户名前缀
    private static List<String> DEFAULT_NICKNAME_PREFIX = List.of("生活更美好", "大桔大利", "日富一日", "好柿开花", "柿柿如意", "一椰暴富", "大柚所为", "杨梅吐气", "天生荔枝");

    @Autowired
    private WechatConfigProperties wechatConfigProperties;

    @Autowired
    private JwtProperties jwtProperties;

    @Override
    public LoginVo login(UserLoginRequestDto dto) {
        //1. 向微信官方发起请求,获取openid,如果获取不到,就是登录失败
        // https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("appid",wechatConfigProperties.getAppid());
        paramMap.put("secret",wechatConfigProperties.getSecret());
        paramMap.put("js_code",dto.getCode());
        paramMap.put("grant_type","authorization_code");
        String result = HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session", paramMap);
        HashMap<String,String> map = JSON.parseObject(result, HashMap.class);
        String openid = map.get("openid");
        if (StrUtil.isEmpty(openid)){
            throw new BusinessException("微信登录失败");
        }

        //2. 从微信官方获取当前用户的手机号
        //2-1 从微信官方获取当前openid对应的token
        // https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/miniapp/openapi/getaccesstoken.html
        HashMap<String, Object> paramMap1 = new HashMap<>();
        paramMap1.put("appid",wechatConfigProperties.getAppid());
        paramMap1.put("secret",wechatConfigProperties.getSecret());
        paramMap1.put("grant_type","client_credential");
        String result1 = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token", paramMap1);
        HashMap<String,String> map1 = JSON.parseObject(result1, HashMap.class);
        String accessToken = map1.get("access_token");
        if (StrUtil.isEmpty(accessToken)){
            throw new BusinessException("微信登录失败");
        }
        //2-2 根据token从微信官方获取当前用户的手机号
        // https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html#%E4%BA%91%E8%B0%83%E7%94%A8
        HashMap<String, Object> paramMap2 = new HashMap<>();
        paramMap2.put("code",dto.getPhoneCode());
        String result2 = HttpUtil.post("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+accessToken, JSON.toJSONString(paramMap2));
        JSONObject jsonObject = JSON.parseObject(result2);
        if (jsonObject.getInteger("errcode")!=0) {
            throw new BusinessException(jsonObject.getString("errmsg"));
        }
        String phoneNumber = jsonObject.getJSONObject("phone_info").getString("phoneNumber");

        //3. 根据返回的openid确认是否是新用户,如果是则保存到数据表中,否则更新用户手机号
        LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Member::getOpenId,openid);
        Member member = getBaseMapper().selectOne(wrapper);
        if (member == null){//新增
            member = new Member();
            member.setOpenId(openid);
            member.setPhone(phoneNumber);
            member.setName(RandomUtil.randomEle(DEFAULT_NICKNAME_PREFIX)+phoneNumber.substring(7,11));
            getBaseMapper().insert(member);
        }else{//更新
            member.setPhone(phoneNumber);
            getBaseMapper().updateById(member);
        }

        //4. 生成token
        Map<String, Object> claims = new HashMap<>();
        claims.put("userid", member.getId());
        claims.put("sub", member.getName());
        String token = JwtUtil.createJWT(jwtProperties.getBase64EncodedSecretKey(), jwtProperties.getTtl(), claims);

        //5. 组装返回结果
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setNickName(member.getName());

        return loginVo;
    }
    @Autowired
    private ContractMapper contractMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private ElderMapper elderMapper;

    @Override
    public PageResponse<MemberVo> findByPage(Integer pageNum, Integer pageSize, String phone, String nickname) {
        //1. 根据条件查询member表
        Page<Member> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StrUtil.isNotEmpty(nickname), Member::getName, nickname)
                .like(StrUtil.isNotEmpty(phone), Member::getPhone, phone);
        page = getBaseMapper().selectPage(page, wrapper);

        //2. 遍历page.Records, 将得到每一个member对象转换成membervo
        List<MemberVo> memberVoList = page.getRecords().stream().map(member -> {
            //1. 复制
            MemberVo memberVo = BeanUtil.copyProperties(member, MemberVo.class);

            //2. 老人姓名(memberVo-->客户id-->去中间表-->老人id-->老人表-->姓名)
            List<Elder> list = elderMapper.findByMemberId(memberVo.getId());
            if (CollUtil.isNotEmpty(list)){
                memberVo.setElderNames(list.stream().map(elder -> elder.getName()).collect(Collectors.joining(",")));
            }

            //3. 是否签约
            //select count(*) from app_contract where phone = 手机号  and status = 1
            LambdaQueryWrapper<Contract> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(Contract::getMemberPhone,memberVo.getPhone())
                    .eq(Contract::getStatus,1);
            Long count1 = contractMapper.selectCount(wrapper1);
            memberVo.setIsSign(count1 > 0 ? "是" : "否");

            //4. 下单次数
            //select count(*) from app_order where member_id = and payment_status = 2 and status = 3
            LambdaQueryWrapper<Order> wrapper2 = new LambdaQueryWrapper<>();
            wrapper2.eq(Order::getMemberId,memberVo.getId())
                    .eq(Order::getPaymentStatus,2)
                    .eq(Order::getStatus,3);
            Long count2 = orderMapper.selectCount(wrapper2);
            memberVo.setOrderCount(count2.intValue());

            return memberVo;
        }).collect(Collectors.toList());

        //3. 返回结果
        return new PageResponse<>(page, memberVoList);
    }
}
